//-----------------------------------------------------------------------
// <copyright file="IndexersAcceptanceTest.cs" company="NMock2">
//
//   http://www.sourceforge.net/projects/NMock2
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
// </copyright>
// This is the easiest way to ignore StyleCop rules on this file, even if we shouldn't use this tag:
// <auto-generated />
//-----------------------------------------------------------------------
namespace NMock2.AcceptanceTests
{
    using System;
    using NMock2.Internal;
    using NUnit.Framework;

    public interface IIndexed
    {
        string this[string s, string t] { get; set; }
    }

    public abstract class Indexed : IIndexed
    {
        public abstract string this[string s, string t] { get; set; }
    }
    
    [TestFixture]
    public class IndexersAcceptanceTest : AcceptanceTestBase
    {
        [Test]
        public void CanExpectIndexedGetterOnInterface()
        {
            AssertCanExpectIndexedGetter(Mocks.NewMock<IIndexed>());
        }

        [Test, Class]
        public void CanExpectIndexedGetterOnClass()
        {
            AssertCanExpectIndexedGetter(Mocks.NewMock<Indexed>());
        }

        private void AssertCanExpectIndexedGetter(IIndexed indexed)
        {
            Stub.On(indexed).Get["Bill", "Gates"].Will(Return.Value("Microsoft"));
            Stub.On(indexed).Get["Steve", "Jobs"].Will(Return.Value("Apple"));

            Assert.AreEqual("Microsoft", indexed["Bill", "Gates"], "Bill, Gates");
            Assert.AreEqual("Apple", indexed["Steve", "Jobs"], "Steve, Jobs");
        }

        [Test]
        public void CanExpectIndexedSetterOnInterface()
        {
            AssertCanExpectIndexedSetter(Mocks.NewMock<IIndexed>());
        }

        [Test, Class]
        public void CanExpectIndexedSetterOnClass()
        {
            AssertCanExpectIndexedSetter(Mocks.NewMock<Indexed>());
        }

        private void AssertCanExpectIndexedSetter(IIndexed indexed)
        {
            Expect.Once.On(indexed).Set["Bill", "Gates"].To("Microsoft");

            indexed["Bill", "Gates"] = "Microsoft";
        }
    
        [Test]
        public void ErrorMessagesContainNameOfIndexedGetterNotHiddenMethodOnInterface()
        {
            AssertErrorMessagesContainNameOfIndexedGetterNotHiddenMethod(Mocks.NewMock<IIndexed>());
        }

        [Test, Class]
        public void ErrorMessagesContainNameOfIndexedGetterNotHiddenMethodOnClass()
        {
            AssertErrorMessagesContainNameOfIndexedGetterNotHiddenMethod(Mocks.NewMock<Indexed>());
        }

        private void AssertErrorMessagesContainNameOfIndexedGetterNotHiddenMethod(IIndexed indexed)
        {
            SkipVerificationForThisTest();
            
            Stub.On(indexed).Get["Bill", "Gates"].Will(Return.Value("Microsoft"));

            try
            {
                String.Intern(indexed["Steve", "Jobs"]);
            }
            catch (ExpectationException e)
            {
                Assert.IsTrue(e.Message.IndexOf("get_Item") < 0,
                              "message should not contain get_Item");

                Assert.IsTrue(e.Message.IndexOf("indexed[equal to \"Bill\", equal to \"Gates\"]") >= 0,
                    "message should contain indexed[equal to \"Bill\", equal to \"Gates\"]\nWas: " + e.Message);
                Assert.IsTrue(e.Message.IndexOf("indexed[\"Steve\", \"Jobs\"]") >= 0,
                    "message should contain indexed[\"Steve\", \"Jobs\"]\nWas: " + e.Message);
            }
        }

        [Test]
        public void ErrorMessagesContainNameOfIndexedSetterNotHiddenMethodOnInterface()
        {
            AssertErrorMessagesContainNameOfIndexedSetterNotHiddenMethod(Mocks.NewMock<IIndexed>());
        }

        [Test, Class]
        public void ErrorMessagesContainNameOfIndexedSetterNotHiddenMethodOnClass()
        {
            AssertErrorMessagesContainNameOfIndexedSetterNotHiddenMethod(Mocks.NewMock<Indexed>());
        }

        private void AssertErrorMessagesContainNameOfIndexedSetterNotHiddenMethod(IIndexed indexed)
        {
            SkipVerificationForThisTest();
            
            Expect.Once.On(indexed).Set["Bill","Gates"].To("Microsoft");
            
            try
            {
                indexed["Steve","Jobs"] = "Apple";
            }
            catch (ExpectationException e)
            {
                Assert.IsTrue(e.Message.IndexOf("set_Item") < 0,
                    "message should not contain set_Item" );

                Assert.IsTrue(e.Message.IndexOf("indexed[equal to \"Bill\", equal to \"Gates\"] = (equal to \"Microsoft\")") >= 0,
                    "message should contain indexed[equal to \"Bill\", equal to \"Gates\"] = \"Microsoft\"\nWas: " + e.Message );
                Assert.IsTrue(e.Message.IndexOf("indexed[\"Steve\", \"Jobs\"] = \"Apple\"") >= 0,
                    "message should contain indexed[\"Steve\", \"Jobs\"] = \"Apple\"\nWas: " + e.Message );
            }
        }
    }
}
